#ifndef SCHEDULEPAGE_H
#define SCHEDULEPAGE_H
#define NUM_OF_PROCESS 6
#define TIME_SLICE 5
#define BACKUP_MAX 101
#define OSMEMORY 6
#define READYQUEUE_MAX 6
#define MEMORYSIZE 32
#define NOTPARTIED 0

#include <QWidget>
#include "pcb.h"
#include <QQueue>
#include <QStandardItemModel>
#include <QTabWidget>
#include <QTimer>
#include <QtSql/QSqlDatabase>
#include "backupque.h"
#include "addwork.h"
#include "algorithm"
#include <QMessageBox>
#include "memoryusage.h"


struct UnpartitionTable//未分分区表的单元项
{
    UnpartitionTable(int beginValue, int widthValue, int statusValue){
        beginAddr = beginValue+1;
        width = widthValue;
        tableStatus = statusValue;//0-->empty
    }

    int beginAddr;
    int width;
    int tableStatus;
};

namespace Ui {
class SchedulePage;
}

class SchedulePage : public QWidget
{
    Q_OBJECT

public:
    explicit SchedulePage(QWidget *parent = nullptr);
    ~SchedulePage();
    QTimer *timer;

private slots:

    void on_startButton_clicked();

    void on_backupQueButton_clicked();

    void on_addWorkButton_clicked();

    void on_random_clicked();

    void on_readyQue_customContextMenuRequested(const QPoint &pos);//右键点击就绪队列
    void on_suspendque_customContextMenuRequested(const QPoint &pos);

//protected:
//    void paintEvent(QPaintEvent *event);//实时绘制界面

    void on_terminateButton_clicked();

    void on_continueButton_clicked();

    void receiveData(PCB*);

    void on_addrassignpatterns_currentIndexChanged(int index);

public:
    void init();//初始化函数
    void initReadyQue();//初始化就绪队列
    void initSuspend();//初始化挂起列表
    void initMemoryPhoto();//初始化内存占用显示图

    void initTimers();
    void stopTimers();
    void addProcessByPrio(PCB *);//按优先级添加进程
    void addProcessByRunt(PCB *);//按短作业优先添加进程
    void addProcessByFC(PCB *);

    void delFirstOfBackup();
    void timerEvent(QTimerEvent *eve) Q_DECL_OVERRIDE;

    void cpuScheduleByPrio();//动态优先权
    void ifOccurQzByPrio();//抢占

    void RRSchedule();//时间片轮转算法
    void ifFinishInSlice();//轮转

    void FCFSSchedule();//先到先服务

    void SJFSchedule();//短作业优先s
    void ifOccurQzByRunt();//抢占

    PCB* popReadyProcs();
    void updateReadyQueData();//更新就绪队列信息
    void updateSusbendData();//更新挂起队列
    void updateCpuStatus();//更新cpu状态
    void creatSelectAlogrithmMenu();//创建算法选择菜单
    void randomProcess();

//    QSqlDatabase getDB();

    void resizeEvent(QResizeEvent *);

    bool ifCanAddToMemory(PCB * p);//是否内存分配也成功，新加进主界面的ready队列

    void initMemoryTable();//初始化内存展示表
    void initMemory();//初始化代表内存的数组
    void initUnpartiTable();//初始化未分分区表
    void refreshUnpartiTable();//刷新未分分区表展示表格
    void refreshMemoryTable();//根据进程PCB信息刷新内存展示表格
    void unpartitionTableSort();//对未分分区表的各项按照起址进行小到大的排序
    static bool cmpOfUnptTableSort(const UnpartitionTable *info1, const UnpartitionTable *info2);
    int sumOfUnptTableSpace();//返回所有剩余空间之和
    bool isEveryEnough(int procsWidth);//检测函数，是否有未分分区足够
    bool isAllEnough(int procsWidth);//检测函数，未分分区总和是否足够
    int addrAssignment(PCB *targetProcs);//内存分配，分配成功返回1，否则返回0
    int exitMemoryRelease(PCB *leaveProcs);//进程出内存后的内存释放，修改未分分区表内容和内存代表数组的内容，刷新未分分区表展示表格
    void exitMemoryMerge();//合并函数，在进程出主存的时候进行调用，合并内存碎片
    void refreshProcsColors();//更新所有进程（不包括即将要进入的进程）的颜色状态
    void upDateMemoryPhoto();//更新内存盘的展示效果
    void getCurMemoryPercent();//更新当前的内存占比
    void memoryCompaction();//内存紧缩
    void initProcsInMemory();//更新inmemory表（在内存中的进程的指针的集合）
    void memoryProcsUsedSort();//将在内存中的进程按照地址排序
    static bool cmpOfProcsUsedSort(const PCB *, const PCB *);
    void initWaiting();//初始化加载gif动图
    void unpartitionTableSortBySize();//对未分分区表的各项按照空间大小(width)进行小到大的排序
    static bool cmpOfUnptTableSortBySize(const UnpartitionTable *info1, const UnpartitionTable *info2);
    int getIndexByFirst(int procsWidth);//按照最先适应的算法返回的合适下标，找不到返回-1
    int getIndexByBest(int procsWidth);//按照最优适应的算法返回的合适下标，找不到返回-1
    int getIndexByWorst(int procsWidth);//按照最差适应的算法返回的合适下标，找不到返回-1


private:
    Ui::SchedulePage *ui;
    int alogrithm;

    backupQue * backupque;//后备队列页面
    addWork * addwork;//手动添加进程页面
    MemoryUsage * memoryUsage;//内存占用圆环形图

    //计时器
    int time_slice;
    int unit_time;
    int unit_time_prio;
    int timerMemoryPhoto;

    PCB * running;//正在运行的进程
    PCB * suspend[NUM_OF_PROCESS];//挂起队列
    PCB * ready[NUM_OF_PROCESS];//就绪队列
    PCB * unlock[NUM_OF_PROCESS];//解挂队列
    int memory[MEMORYSIZE];//代表内存的数组，32长度

    int proCount;//进程计数器
    int num_in_memory;//内存中的进程总数
    int num_in_suspend;//被挂起的总进程数
    int num_in_backup;//后备队列中的进程数
    int num_unlock;//被解挂的进程，优先等待返回就绪队列

    int curRunTime;//记录运行时间：时间片
    int runModel;

    int addrAssign;

    bool cpuWait;//cpu处理等得是否开始
    bool ifCpuWaitOver;//cpu等待是否完毕
    bool ifCpuSchedule;//是否可以进行下一次cpu调度循环
    bool ifCpuScheduleIsRunning;//cpu调度循环是否正在进行
    int curmemorypercent;//当前的内存占用的百分比

    QList<PCB * > inmemory;//内存中所有进程的集合

    QList<UnpartitionTable*> unpartitionTable;//整个未分分区表
    int timercrush;

};

#endif // SCHEDULEPAGE_H
